home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MacHack 1999
/
MacHack 1999.toast
/
The Hacks
/
CarbonizedMenus
/
source
/
RootMenu.cp
< prev
Wrap
Text File
|
1999-06-26
|
20KB
|
632 lines
/****************************************************************************************
RootMenu.cp
Copyright © 1999 Red Shed Software. All rights reserved.
by Jonathan 'Wolf' Rentzsch (jon@redshed.net)
Commenter Date Comment
--------- ----------------- -----------------------------------------------------
wolf Fri, Jun 25, 1999 Created.
************************************************************************************/
#include "RootMenu.h"
#include "MacExceptions.h"
#include "FontInfo.h"
#include "require.h"
#include "TextServices.h"
#include "XProcessInfoRec.h"
#include "MenuList.h"
#include "AutoPort.h"
const RGBColor kBottomRightColor = kLightGray;
const RGBColor kTopLeftColor = kUnionGray;
const RGBColor kBodyColor = kLighterGray;
const short kTopMargin = 4;
const short kLeftMargin = 4;
const short kBottomMargin = 6;
const short kRightMargin = 4;
const short kIconMargin = 6;
const short kCmdMargin = 4;
const short kSubMenuWidth = 6;
const short kIconWidth = 9;
const short kIconHalfHieght = 4;
list< AbstractMenuWindow* > gMenus;
Point gRootLoc = { 5, 5 };
bool
ExtractMenuIcon(
MenuHandle menu,
Handle &iconSuite );
short
GetWindowWidth(
WindowRecord *w );
Point
GetWindowLoc(
WindowRecord *w );
void
DrawBlackBox(
const Rect &rect );
void
DrawGrayBox(
const Rect &rect );
void
DrawWhiteBox(
const Rect &rect );
void
DrawSubMenu(
const Rect &rect );
CleanUp gCleanUp;
/****************************************************************************************
Commenter Date Comment
--------- ----------------- -----------------------------------------------------
wolf Fri, Jun 25, 1999 Created.
************************************************************************************/
AbstractMenuWindow::AbstractMenuWindow()
{
Rect r = { 40, 40, 300, 300 };
WindowPtr w = nil;
ThrowIfErr( NewServiceWindow( window(), &r, "\p", true, plainDBox, (WindowPtr) -1,
true, (ComponentInstance) kCurrentProcess, &w ), nil );
window_.refCon = (long) this;
SetPort( window() );
PenNormal();
short fontID;
GetFNum( "\pHelvetica", &fontID );
TextFont( fontID );
TextFace( bold );
gMenus.push_back( this );
}
/****************************************************************************************
Commenter Date Comment
--------- ----------------- -----------------------------------------------------
wolf Fri, Jun 25, 1999 Created.
************************************************************************************/
AbstractMenuWindow::~AbstractMenuWindow()
{
gMenus.remove( this );
CloseServiceWindow( window() );
}
/****************************************************************************************
Commenter Date Comment
--------- ----------------- -----------------------------------------------------
wolf Fri, Jun 25, 1999 Created.
************************************************************************************/
RootMenu::RootMenu()
{
//-------------------------------------------------
// Figure out the width & height of the window
MoveWindow( window(), gRootLoc.h, gRootLoc.v, false );
short minWidth = 0;// kLeftMargin + kCmdMargin + kRightMargin;
// Process Window Title
Str255 s;
FrontProcess frontProcess( s );
short x = StringWidth( s );
if( x > minWidth )
minWidth = x;
// Apple Menu Item
if( 16 > minWidth )
minWidth = 16;
// "Normal" Menus
MenuListHandle list = GetMenuList();
RequireHandle( list );
UInt16 count = (**list).menuCount / 6;
for( UInt16 index = 1; index < count; ++index ) { // Skip over apple menu
MenuHandle menu = (**list).menus[ index ].menu;
RequireHandle( menu );
Handle iconHandle = nil;
bool hasIcon = ExtractMenuIcon( menu, iconHandle );
RequireHandleIfNotNil( iconHandle );
if( !hasIcon ) {
BlockMoveData( &menu[0]->menuData, s, menu[0]->menuData[ 0 ] + 1 );
x = StringWidth( s );
if( x > minWidth )
minWidth = x;
}
}
minWidth += kLeftMargin + kCmdMargin + kSubMenuWidth + kRightMargin;
short menuItemCount = 1 + count;
short minHeight = menuItemCount * (kTopMargin + GetMaxFontHeight( "\pHelvetica", 12, bold ) + kBottomMargin);
SizeWindow( window(), minWidth, minHeight, false );
Draw();
}
/****************************************************************************************
Commenter Date Comment
--------- ----------------- -----------------------------------------------------
wolf Fri, Jun 25, 1999 Created.
************************************************************************************/
void
RootMenu::Draw()
{
AutoPort autoPort( window() );
short itemHeight = kTopMargin + GetMaxFontHeight( "\pHelvetica", 12, bold ) + kBottomMargin;
Rect curRect = { 0, 0, itemHeight, GetWindowWidth( &window_ ) };
// Title
DrawBlackBox( curRect );
Str255 s;
FrontProcess frontProcess( s );
MoveTo( curRect.left + kLeftMargin, curRect.bottom - kBottomMargin );
RGBForeColor( &kRGBWhite );
DrawString( s );
// Apple Menu
curRect.top += itemHeight;
curRect.bottom += itemHeight;
DrawGrayBox( curRect );
short diff = (itemHeight - 16) / 2;
Rect iconRect = { curRect.top + diff, curRect.left + kLeftMargin,
curRect.bottom - diff, curRect.left + kLeftMargin + 16 };
ThrowIfErr( PlotIconID( &iconRect, kAlignNone, kTransformNone, -16386 ), nil );
DrawSubMenu( curRect );
// Normal Menus
MenuListHandle list = GetMenuList();
RequireHandle( list );
UInt16 count = (**list).menuCount / 6;
for( UInt16 index = 1; index < count; ++index ) { // Skip over apple menu
MenuHandle menu = (**list).menus[ index ].menu;
RequireHandle( menu );
Handle iconHandle = nil;
bool hasIcon = ExtractMenuIcon( menu, iconHandle );
RequireHandleIfNotNil( iconHandle );
curRect.top += itemHeight;
curRect.bottom += itemHeight;
DrawGrayBox( curRect );
if( hasIcon ) {
short diff = (itemHeight - 16) / 2;
Rect iconRect = { curRect.top + diff, curRect.left + kLeftMargin,
curRect.bottom - diff, curRect.left + kLeftMargin + 16 };
ThrowIfErr( PlotIconSuite( &iconRect, kAlignNone, kTransformNone, (IconSuiteRef) iconHandle ), nil );
DrawSubMenu( curRect );
} else {
MoveTo( curRect.left + kLeftMargin, curRect.bottom - kBottomMargin );
RGBForeColor( &kRGBBlack );
BlockMoveData( &menu[0]->menuData, s, menu[0]->menuData[ 0 ] + 1 );
DrawString( s );
DrawSubMenu( curRect );
}
}
}
/****************************************************************************************
Commenter Date Comment
--------- ----------------- -----------------------------------------------------
wolf Sat, Jun 26, 1999 Created.
************************************************************************************/
void
RootMenu::MouseDown(
EventRecord *event )
{
AutoPort autoPort( window() );
short itemHeight = kTopMargin + GetMaxFontHeight( "\pHelvetica", 12, bold ) + kBottomMargin;
Rect curRect = { 0, 0, itemHeight, GetWindowWidth( &window_ ) };
Point where = event->where;
GlobalToLocal( &where );
// Title
if( PtInRect( where, &curRect ) ) {
DragWindow( window(), event->where, &qd.screenBits.bounds );
gRootLoc = GetWindowLoc( &window_ );
return;
}
// Apple Menu
curRect.top += itemHeight;
curRect.bottom += itemHeight;
if( PtInRect( where, &curRect ) ) {
DrawWhiteBox( curRect );
short diff = (itemHeight - 16) / 2;
Rect iconRect = { curRect.top + diff, curRect.left + kLeftMargin,
curRect.bottom - diff, curRect.left + kLeftMargin + 16 };
ThrowIfErr( PlotIconID( &iconRect, kAlignNone, kTransformNone, -16386 ), nil );
DrawSubMenu( curRect );
while( !LMGetMouseButtonState() ){}
DrawGrayBox( curRect );
DrawSubMenu( curRect );
ThrowIfErr( PlotIconID( &iconRect, kAlignNone, kTransformNone, -16386 ), nil );
GetMouse( &where );
if( PtInRect( where, &curRect ) ) {
new NormalMenu( (**GetMenuList()).menus[ 0 ].menu, true );
}
}
// Menus
Str255 s;
MenuListHandle list = GetMenuList();
RequireHandle( list );
UInt16 count = (**list).menuCount / 6;
for( UInt16 index = 1; index < count; ++index ) {
MenuHandle menu = (**list).menus[ index ].menu;
RequireHandle( menu );
Handle iconHandle = nil;
bool hasIcon = ExtractMenuIcon( menu, iconHandle );
RequireHandleIfNotNil( iconHandle );
curRect.top += itemHeight;
curRect.bottom += itemHeight;
if( PtInRect( where, &curRect ) ) {
DrawWhiteBox( curRect );
if( hasIcon ) {
short diff = (itemHeight - 16) / 2;
Rect iconRect = { curRect.top + diff, curRect.left + kLeftMargin,
curRect.bottom - diff, curRect.left + kLeftMargin + 16 };
ThrowIfErr( PlotIconSuite( &iconRect, kAlignNone, kTransformNone, (IconSuiteRef) iconHandle ), nil );
DrawSubMenu( curRect );
} else {
MoveTo( curRect.left + kLeftMargin, curRect.bottom - kBottomMargin );
RGBForeColor( &kRGBBlack );
BlockMoveData( &menu[0]->menuData, s, menu[0]->menuData[ 0 ] + 1 );
DrawString( s );
DrawSubMenu( curRect );
}
while( !LMGetMouseButtonState() ){}
DrawGrayBox( curRect );
if( hasIcon ) {
short diff = (itemHeight - 16) / 2;
Rect iconRect = { curRect.top + diff, curRect.left + kLeftMargin,
curRect.bottom - diff, curRect.left + kLeftMargin + 16 };
ThrowIfErr( PlotIconSuite( &iconRect, kAlignNone, kTransformNone, (IconSuiteRef) iconHandle ), nil );
DrawSubMenu( curRect );
} else {
MoveTo( curRect.left + kLeftMargin, curRect.bottom - kBottomMargin );
RGBForeColor( &kRGBBlack );
BlockMoveData( &menu[0]->menuData, s, menu[0]->menuData[ 0 ] + 1 );
DrawString( s );
DrawSubMenu( curRect );
}
GetMouse( &where );
if( PtInRect( where, &curRect ) ) {
new NormalMenu( menu );
}
return;
}
}
}
/****************************************************************************************
Commenter Date Comment
--------- ----------------- -----------------------------------------------------
wolf Fri, Jun 25, 1999 Created.
************************************************************************************/
CleanUp::~CleanUp()
{
list< AbstractMenuWindow* >::iterator menuB = gMenus.begin();
list< AbstractMenuWindow* >::iterator menuE = gMenus.end();
while( menuB != menuE ) {
delete *menuB;
menuB = gMenus.begin();
}
}
/****************************************************************************************
Commenter Date Comment
--------- ----------------- -----------------------------------------------------
wolf Fri, Jun 25, 1999 Created.
************************************************************************************/
short
GetWindowWidth(
WindowRecord *w )
{
RequirePtr( w );
RgnHandle rgn = w->contRgn;
RequireHandle( rgn );
Rect rect = (**rgn).rgnBBox;
return( rect.right - rect.left );
}
/****************************************************************************************
Commenter Date Comment
--------- ----------------- -----------------------------------------------------
wolf Fri, Jun 25, 1999 Created.
************************************************************************************/
Point
GetWindowLoc(
WindowRecord *w )
{
RequirePtr( w );
RgnHandle rgn = w->strucRgn;
RequireHandle( rgn );
Rect rect = (**rgn).rgnBBox;
return( *(Point*) &rect );
}
/****************************************************************************************
Commenter Date Comment
--------- ----------------- -----------------------------------------------------
wolf Fri, Jun 25, 1999 Created.
************************************************************************************/
void
DrawBlackBox(
const Rect &rect )
{
RGBForeColor( &kBottomRightColor );
MoveTo( rect.right - 1, rect.top );
LineTo( rect.right - 1, rect.bottom - 1 );
LineTo( rect.left, rect.bottom - 1 );
RGBForeColor( &kTopLeftColor );
LineTo( rect.left, rect.top );
LineTo( rect.right, rect.top );
RGBForeColor( &kRGBBlack );
Rect fillRect = { rect.top + 1, rect.left + 1, rect.bottom - 1, rect.right - 1 };
FillRect( &fillRect, &qd.black );
}
/****************************************************************************************
Commenter Date Comment
--------- ----------------- -----------------------------------------------------
wolf Fri, Jun 25, 1999 Created.
************************************************************************************/
void
DrawGrayBox(
const Rect &rect )
{
RGBForeColor( &kBottomRightColor );
MoveTo( rect.right - 1, rect.top );
LineTo( rect.right - 1, rect.bottom - 1 );
LineTo( rect.left, rect.bottom - 1 );
RGBForeColor( &kTopLeftColor );
LineTo( rect.left, rect.top );
LineTo( rect.right, rect.top );
RGBForeColor( &kBodyColor );
Rect fillRect = { rect.top + 1, rect.left + 1, rect.bottom - 1, rect.right - 1 };
FillRect( &fillRect, &qd.black );
RGBForeColor( &kRGBBlack );
}
/****************************************************************************************
Commenter Date Comment
--------- ----------------- -----------------------------------------------------
wolf Fri, Jun 25, 1999 Created.
************************************************************************************/
void
DrawWhiteBox(
const Rect &rect )
{
RGBForeColor( &kBottomRightColor );
MoveTo( rect.right - 1, rect.top );
LineTo( rect.right - 1, rect.bottom - 1 );
LineTo( rect.left, rect.bottom - 1 );
RGBForeColor( &kTopLeftColor );
LineTo( rect.left, rect.top );
LineTo( rect.right, rect.top );
RGBForeColor( &kRGBWhite );
Rect fillRect = { rect.top + 1, rect.left + 1, rect.bottom - 1, rect.right - 1 };
FillRect( &fillRect, &qd.black );
RGBForeColor( &kRGBBlack );
}
/****************************************************************************************
Commenter Date Comment
--------- ----------------- -----------------------------------------------------
wolf Fri, Jun 25, 1999 Created.
************************************************************************************/
void
DrawSubMenu(
const Rect &rect )
{
Point right = { rect.top + ((rect.bottom - rect.top)/2), rect.right - kIconMargin };
Point topLeft = { right.v - kIconHalfHieght, right.h - kIconWidth };
Point bottomLeft = { right.v + kIconHalfHieght, right.h - kIconWidth };
//Point right = { rect.top + (rect.bottom - rect.top), rect.right - kIconMargin };
//Point topLeft = { right.h + kIconHalfHieght, right.v - kIconWidth };
//Point bottomLeft = { right.h - kIconHalfHieght, right.v - kIconWidth };
RGBForeColor( &kBottomRightColor );
MoveTo( topLeft.h, topLeft.v );
LineTo( right.h, right.v );
RGBForeColor( &kTopLeftColor );
LineTo( bottomLeft.h, bottomLeft.v );
RGBForeColor( &kRGBBlack );
LineTo( topLeft.h, topLeft.v );
}
/****************************************************************************************
Commenter Date Comment
--------- ----------------- -----------------------------------------------------
wolf Sat, Jun 26, 1999 Created.
************************************************************************************/
NormalMenu::NormalMenu(
MenuHandle menu,
bool apple )
: menu_( menu ), apple_( apple )
{
MoveWindow( window(), 5 + gRootLoc.h + GetWindowWidth( (WindowRecord*) (*gMenus.begin())->window() ), 5, false );
short minWidth = 0;// kLeftMargin + kCmdMargin + kRightMargin;
// Process Window Title
Handle icon;
if( apple ) {
if( 16 > minWidth )
minWidth = 16;
} else {
if( ExtractMenuIcon( menu_, icon ) ) {
if( 16 > minWidth )
minWidth = 16;
} else {
Str255 s;
BlockMoveData( &menu[0]->menuData, s, menu[0]->menuData[ 0 ] + 1 );
short x = StringWidth( s );
if( x > minWidth )
minWidth = x;
}
}
// "Normal" Menus
Str255 s;
short itemCount = CountMenuItems( menu );
for( short itemIndex = 1; itemIndex < itemCount; ++itemIndex ) {
GetMenuItemText( menu, itemIndex, s );
short x = StringWidth( s );
if( x > minWidth )
minWidth = x;
}
minWidth += kLeftMargin + kCmdMargin + kSubMenuWidth + kRightMargin;
short menuItemCount = 1 + itemCount;
short minHeight = menuItemCount * (kTopMargin + GetMaxFontHeight( "\pHelvetica", 12, bold ) + kBottomMargin);
SizeWindow( window(), minWidth, minHeight, false );
Draw();
}
/****************************************************************************************
Commenter Date Comment
--------- ----------------- -----------------------------------------------------
wolf Sat, Jun 26, 1999 Created.
************************************************************************************/
void
NormalMenu::Draw()
{
AutoPort autoPort( window() );
short itemHeight = kTopMargin + GetMaxFontHeight( "\pHelvetica", 12, bold ) + kBottomMargin;
Rect curRect = { 0, 0, itemHeight, GetWindowWidth( &window_ ) };
// Title
Handle icon;
Str255 s;
DrawBlackBox( curRect );
if( apple_ ) {
short diff = (itemHeight - 16) / 2;
Rect iconRect = { curRect.top + diff, curRect.left + kLeftMargin,
curRect.bottom - diff, curRect.left + kLeftMargin + 16 };
ThrowIfErr( PlotIconID( &iconRect, kAlignNone, kTransformNone, -16386 ), nil );
} else {
if( ExtractMenuIcon( menu_, icon ) ) {
short diff = (itemHeight - 16) / 2;
Rect iconRect = { curRect.top + diff, curRect.left + kLeftMargin,
curRect.bottom - diff, curRect.left + kLeftMargin + 16 };
ThrowIfErr( PlotIconSuite( &iconRect, kAlignNone, kTransformNone, (IconSuiteRef) icon ), nil );
} else {
BlockMoveData( &menu_[0]->menuData, s, menu_[0]->menuData[ 0 ] + 1 );
MoveTo( curRect.left + kLeftMargin, curRect.bottom - kBottomMargin );
RGBForeColor( &kRGBWhite );
DrawString( s );
}
}
/*( Title
DrawBlackBox( curRect );
BlockMoveData( &menu_[0]->menuData, s, menu_[0]->menuData[ 0 ] + 1 );
MoveTo( curRect.left + kLeftMargin, curRect.bottom - kBottomMargin );
RGBForeColor( &kRGBWhite );
DrawString( s );*/
// "Normal" Menus
short itemCount = CountMenuItems( menu_ );
for( short itemIndex = 1; itemIndex <= itemCount; ++itemIndex ) {
GetMenuItemText( menu_, itemIndex, s );
curRect.top += itemHeight;
curRect.bottom += itemHeight;
DrawGrayBox( curRect );
MoveTo( curRect.left + kLeftMargin, curRect.bottom - kBottomMargin );
RGBForeColor( &kRGBBlack );
DrawString( s );
}
}
/****************************************************************************************
Commenter Date Comment
--------- ----------------- -----------------------------------------------------
wolf Sat, Jun 26, 1999 Created.
************************************************************************************/
void
NormalMenu::MouseDown(
EventRecord *event )
{
AutoPort autoPort( window() );
Str255 s;
short itemHeight = kTopMargin + GetMaxFontHeight( "\pHelvetica", 12, bold ) + kBottomMargin;
Rect curRect = { 0, 0, itemHeight, GetWindowWidth( &window_ ) };
Point where = event->where;
GlobalToLocal( &where );
// Title
if( PtInRect( where, &curRect ) ) {
DragWindow( window(), event->where, &qd.screenBits.bounds );
return;
}
// "Normal" Menus
short itemCount = CountMenuItems( menu_ );
for( short itemIndex = 1; itemIndex <= itemCount; ++itemIndex ) {
GetMenuItemText( menu_, itemIndex, s );
curRect.top += itemHeight;
curRect.bottom += itemHeight;
if( PtInRect( where, &curRect ) ) {
GetMenuItemText( menu_, itemIndex, s );
DrawWhiteBox( curRect );
MoveTo( curRect.left + kLeftMargin, curRect.bottom - kBottomMargin );
RGBForeColor( &kRGBBlack );
DrawString( s );
while( !LMGetMouseButtonState() ){}
DrawGrayBox( curRect );
MoveTo( curRect.left + kLeftMargin, curRect.bottom - kBottomMargin );
RGBForeColor( &kRGBBlack );
DrawString( s );
GetMouse( &where );
if( PtInRect( where, &curRect ) ) {
SysBeep( 20 );
}
}
}
}